package com.myproject.utils; // 工具类所在的包

import java.util.*; // 集合工具
import java.util.function.Function; // 函数式接口
import java.util.stream.Collectors; // 流收集器
import javax.crypto.SecretKey; // 加密密钥接口
import org.springframework.beans.factory.annotation.Value; // 值注入注解
import org.springframework.security.core.GrantedAuthority; // 权限接口
import org.springframework.stereotype.Component; // 组件注解
import io.jsonwebtoken.*; // JWT相关类
import io.jsonwebtoken.io.Decoders; // 解码工具
import io.jsonwebtoken.security.Keys; // 密钥工具

@Component // 标记为Spring组件
public class JwtUtils { // JWT工具类

	@Value("${jwt.secret}") // 从配置注入JWT密钥
	private String secret;

	@Value("${jwt.expiration}") // 从配置注入JWT过期时间(秒)
	private Long expiration;

	// 密钥优化：避免重复解码[5](@ref)
	private SecretKey getSigningKey() {
		return Keys.hmacShaKeyFor(Decoders.BASE64.decode(secret)); // BASE64解码后生成HMAC密钥
	}

	public String generateToken(String username) {
		Map<String, Object> claims = new HashMap<>();
		return createToken(claims, username);
	}

	// 生成JWT令牌
	public String generateToken(String username, Collection<? extends GrantedAuthority> authorities) {
		Map<String, Object> claims = new HashMap<>(); // 创建声明(claims)映射
		if (authorities != null) {
			// 将权限集合转换为权限字符串列表
			claims.put("authorities",
					authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
		}
		return createToken(claims, username); // 创建令牌
	}

	// 创建JWT令牌(内部方法)
	private String createToken(Map<String, Object> claims, String subject) {
		return Jwts.builder()
				.claims(claims) // 设置声明
				.subject(subject) // 设置主题(用户名)
				.issuedAt(new Date()) // 设置签发时间
				.expiration(new Date(System.currentTimeMillis() + expiration * 1000)) // 设置过期时间
				.signWith(getSigningKey(), Jwts.SIG.HS256) // 使用HS256算法签名
				.compact(); // 生成紧凑字符串
	}

	// 安全增强：防止空算法攻击[5](@ref)
	public Claims extractAllClaims(String token) {
		// 验证签名并解析令牌
		return Jwts.parser()
				.verifyWith(getSigningKey()) // 设置验证密钥
				.build()
				.parseSignedClaims(token) // 解析签名令牌
				.getPayload(); // 获取声明部分
	}

	// 验证逻辑优化：分离基础验证和用户验证
	public Boolean validateTokenStructure(String token) {
		try {
			extractAllClaims(token); // 尝试解析令牌
			return true; // 解析成功返回true
		} catch (JwtException | IllegalArgumentException e) {
			return false; // 解析失败返回false
		}
	}

	// 从令牌提取用户名
	public String extractUsername(String token) {
		return extractClaim(token, Claims::getSubject); // 提取subject声明
	}

	// 通用声明提取方法
	private <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
		final Claims claims = extractAllClaims(token); // 先提取所有声明
		return claimsResolver.apply(claims); // 应用提取函数
	}

	// 检查令牌是否过期
	public Boolean isTokenExpired(String token) {
		return extractClaim(token, Claims::getExpiration) // 提取过期时间
				.before(new Date()); // 与当前时间比较
	}

	// 权限提取优化[4](@ref)
	public Collection<? extends GrantedAuthority> extractAuthorities(String token) {
		Claims claims = extractAllClaims(token); // 提取所有声明
		Object rawAuthorities = claims.get("authorities"); // 获取原始权限列表

		if (rawAuthorities instanceof List<?> authList) {
			return authList.stream()
					.filter(a -> a instanceof String) // 确保元素为String
					.map(a -> (GrantedAuthority) () -> (String) a) // 转换为GrantedAuthority
					.collect(Collectors.toList()); // 收集为列表
		}
		return Collections.emptyList(); // 无权限返回空列表
	}
}